package xymt.novaway.system.service.impl;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import xymt.novaway.common.core.constant.CacheNames;
import xymt.novaway.common.core.constant.SystemConstants;
import xymt.novaway.common.core.constant.TenantConstants;
import xymt.novaway.common.core.domain.model.LoginUser;
import xymt.novaway.common.core.exception.ServiceException;
import xymt.novaway.common.core.service.RoleService;
import xymt.novaway.common.core.utils.MapstructUtils;
import xymt.novaway.common.core.utils.StreamUtils;
import xymt.novaway.common.core.utils.StringUtils;
import xymt.novaway.common.mybatis.core.page.PageQuery;
import xymt.novaway.common.mybatis.core.page.TableDataInfo;
import xymt.novaway.common.satoken.utils.LoginHelper;
import xymt.novaway.system.domain.SysRole;
import xymt.novaway.system.domain.SysRoleDept;
import xymt.novaway.system.domain.SysRoleMenu;
import xymt.novaway.system.domain.SysUserRole;
import xymt.novaway.system.domain.SysRoleDataScopeConfig;
import xymt.novaway.system.domain.SysMenu;
import xymt.novaway.system.domain.bo.SysRoleBo;
import xymt.novaway.system.domain.bo.SysRoleDataScopeConfigBo;
import xymt.novaway.system.domain.vo.SysRoleVo;
import xymt.novaway.system.domain.vo.SysRoleDataScopeConfigVo;
import xymt.novaway.system.domain.vo.MenuPermissionVo;
import xymt.novaway.system.mapper.SysRoleDeptMapper;
import xymt.novaway.system.mapper.SysRoleMapper;
import xymt.novaway.system.mapper.SysRoleMenuMapper;
import xymt.novaway.system.mapper.SysUserRoleMapper;
import xymt.novaway.system.mapper.SysRoleDataScopeConfigMapper;
import xymt.novaway.system.mapper.SysMenuMapper;
import xymt.novaway.system.service.ISysRoleService;
import xymt.novaway.system.annotation.DataScope;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import xymt.novaway.common.core.utils.SpringUtils;

import java.util.*;

/**
 * 角色 业务层处理
 *
 * @author NovaWay
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SysRoleServiceImpl implements ISysRoleService, RoleService {

    private final SysRoleMapper baseMapper;
    private final SysRoleMenuMapper roleMenuMapper;
    private final SysUserRoleMapper userRoleMapper;
    private final SysRoleDeptMapper roleDeptMapper;
    private final SysRoleDataScopeConfigMapper roleDataScopeConfigMapper;
    private final SysMenuMapper menuMapper;
    
    @Autowired
    private DataSource dataSource;

    @Override
    @DataScope(permission = "system:role:list", enableAdvancedFieldPermission = true)
    public TableDataInfo<SysRoleVo> selectPageRoleList(SysRoleBo role, PageQuery pageQuery) {
        Page<SysRoleVo> page = baseMapper.selectPageRoleList(pageQuery.build(), this.buildQueryWrapper(role));
        return TableDataInfo.build(page);
    }

    /**
     * 根据条件分页查询角色数据
     *
     * @param role 角色信息
     * @return 角色数据集合信息
     */
    @Override
    @DataScope(permission = "system:role:list", enableAdvancedFieldPermission = true)
    public List<SysRoleVo> selectRoleList(SysRoleBo role) {
        return baseMapper.selectRoleList(this.buildQueryWrapper(role));
    }

    private Wrapper<SysRole> buildQueryWrapper(SysRoleBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<SysRole> wrapper = Wrappers.query();
        wrapper.eq("r.del_flag", SystemConstants.NORMAL)
            .eq(ObjectUtil.isNotNull(bo.getRoleId()), "r.role_id", bo.getRoleId())
            .like(StringUtils.isNotBlank(bo.getRoleName()), "r.role_name", bo.getRoleName())
            .eq(StringUtils.isNotBlank(bo.getStatus()), "r.status", bo.getStatus())
            .like(StringUtils.isNotBlank(bo.getRoleKey()), "r.role_key", bo.getRoleKey())
            .between(params.get("beginTime") != null && params.get("endTime") != null,
                "r.create_time", params.get("beginTime"), params.get("endTime"))
            .orderByAsc("r.role_sort").orderByAsc("r.create_time");
        
        // 应用数据权限过滤条件（通用方法）
        xymt.novaway.system.utils.DataScopeUtils.applyDataScopeFilter(wrapper);
        
        return wrapper;
    }

    /**
     * 根据用户ID查询角色
     *
     * @param userId 用户ID
     * @return 角色列表
     */
    @Override
    public List<SysRoleVo> selectRolesByUserId(Long userId) {
        return baseMapper.selectRolesByUserId(userId);
    }

    /**
     * 根据用户ID查询角色列表(包含被授权状态)
     *
     * @param userId 用户ID
     * @return 角色列表
     */
    @Override
    public List<SysRoleVo> selectRolesAuthByUserId(Long userId) {
        List<SysRoleVo> userRoles = baseMapper.selectRolesByUserId(userId);
        List<SysRoleVo> roles = selectRoleAll();
        // 使用HashSet提高查找效率
        Set<Long> userRoleIds = StreamUtils.toSet(userRoles, SysRoleVo::getRoleId);
        for (SysRoleVo role : roles) {
            if (userRoleIds.contains(role.getRoleId())) {
                role.setFlag(true);
            }
        }
        return roles;
    }

    /**
     * 根据用户ID查询权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        List<SysRoleVo> perms = baseMapper.selectRolesByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (SysRoleVo perm : perms) {
            if (ObjectUtil.isNotNull(perm)) {
                permsSet.addAll(StringUtils.splitList(perm.getRoleKey().trim()));
            }
        }
        return permsSet;
    }

    /**
     * 查询所有角色
     *
     * @return 角色列表
     */
    @Override
    public List<SysRoleVo> selectRoleAll() {
        return this.selectRoleList(new SysRoleBo());
    }

    /**
     * 根据用户ID获取角色选择框列表
     *
     * @param userId 用户ID
     * @return 选中角色ID列表
     */
    @Override
    public List<Long> selectRoleListByUserId(Long userId) {
        List<SysRoleVo> list = baseMapper.selectRolesByUserId(userId);
        return StreamUtils.toList(list, SysRoleVo::getRoleId);
    }

    /**
     * 通过角色ID查询角色
     *
     * @param roleId 角色ID
     * @return 角色对象信息
     */
    @Override
    public SysRoleVo selectRoleById(Long roleId) {
        return baseMapper.selectRoleById(roleId);
    }

    /**
     * 通过角色ID串查询角色
     *
     * @param roleIds 角色ID串
     * @return 角色列表信息
     */
    @Override
    public List<SysRoleVo> selectRoleByIds(List<Long> roleIds) {
        return baseMapper.selectRoleList(new QueryWrapper<SysRole>()
            .eq("r.status", SystemConstants.NORMAL)
            .in(CollUtil.isNotEmpty(roleIds), "r.role_id", roleIds));
    }

    /**
     * 校验角色名称是否唯一
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public boolean checkRoleNameUnique(SysRoleBo role) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>()
            .eq(SysRole::getRoleName, role.getRoleName())
            .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId()));
        return !exist;
    }

    /**
     * 校验角色权限是否唯一
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    public boolean checkRoleKeyUnique(SysRoleBo role) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>()
            .eq(SysRole::getRoleKey, role.getRoleKey())
            .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId()));
        return !exist;
    }

    /**
     * 校验角色是否允许操作
     *
     * @param role 角色信息
     */
    @Override
    public void checkRoleAllowed(SysRoleBo role) {
        if (ObjectUtil.isNotNull(role.getRoleId()) && LoginHelper.isSuperAdmin(role.getRoleId())) {
            throw new ServiceException("不允许操作超级管理员角色");
        }
        String[] keys = new String[]{TenantConstants.SUPER_ADMIN_ROLE_KEY, TenantConstants.TENANT_ADMIN_ROLE_KEY};
        // 新增不允许使用 管理员标识符
        if (ObjectUtil.isNull(role.getRoleId())
            && StringUtils.equalsAny(role.getRoleKey(), keys)) {
            throw new ServiceException("不允许使用系统内置管理员角色标识符!");
        }
        // 修改不允许修改 管理员标识符
        if (ObjectUtil.isNotNull(role.getRoleId())) {
            SysRole sysRole = baseMapper.selectById(role.getRoleId());
            // 如果标识符不相等 判断为修改了管理员标识符
            if (!StringUtils.equals(sysRole.getRoleKey(), role.getRoleKey())) {
                if (StringUtils.equalsAny(sysRole.getRoleKey(), keys)) {
                    throw new ServiceException("不允许修改系统内置管理员角色标识符!");
                } else if (StringUtils.equalsAny(role.getRoleKey(), keys)) {
                    throw new ServiceException("不允许使用系统内置管理员角色标识符!");
                }
            }
        }
    }

    /**
     * 校验角色是否有数据权限
     *
     * @param roleId 角色id
     */
    @Override
    public void checkRoleDataScope(Long roleId) {
        if (ObjectUtil.isNull(roleId)) {
            return;
        }
        if (LoginHelper.isSuperAdmin()) {
            return;
        }
        List<SysRoleVo> roles = this.selectRoleList(new SysRoleBo(roleId));
        if (CollUtil.isEmpty(roles)) {
            throw new ServiceException("没有权限访问角色数据！");
        }

    }

    /**
     * 通过角色ID查询角色使用数量
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    public long countUserRoleByRoleId(Long roleId) {
        return userRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
    }

    /**
     * 新增保存角色信息
     *
     * @param bo 角色信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertRole(SysRoleBo bo) {
        SysRole role = MapstructUtils.convert(bo, SysRole.class);
        // 新增角色信息
        baseMapper.insert(role);
        bo.setRoleId(role.getRoleId());
        return insertRoleMenu(bo);
    }

    /**
     * 修改保存角色信息
     *
     * @param bo 角色信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateRole(SysRoleBo bo) {
        SysRole role = MapstructUtils.convert(bo, SysRole.class);

        if (SystemConstants.DISABLE.equals(role.getStatus()) && this.countUserRoleByRoleId(role.getRoleId()) > 0) {
            throw new ServiceException("角色已分配，不能禁用!");
        }
        // 修改角色信息
        baseMapper.updateById(role);
        // 删除角色与菜单关联
        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, role.getRoleId()));
        return insertRoleMenu(bo);
    }

    /**
     * 修改角色状态
     *
     * @param roleId 角色ID
     * @param status 角色状态
     * @return 结果
     */
    @Override
    public int updateRoleStatus(Long roleId, String status) {
        if (SystemConstants.DISABLE.equals(status) && this.countUserRoleByRoleId(roleId) > 0) {
            throw new ServiceException("角色已分配，不能禁用!");
        }
        return baseMapper.update(null,
            new LambdaUpdateWrapper<SysRole>()
                .set(SysRole::getStatus, status)
                .eq(SysRole::getRoleId, roleId));
    }

    /**
     * 修改数据权限信息
     *
     * @param bo 角色信息
     * @return 结果
     */
    @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#bo.roleId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int authDataScope(SysRoleBo bo) {
        SysRole role = MapstructUtils.convert(bo, SysRole.class);
        
        // 高级字段权限开关独立控制，不影响原有数据范围
        // enable_advanced_field_permission 字段由前端的开关状态决定
        // 保持原有的数据范围逻辑不变（1-6）
        
        // 修改角色信息
        baseMapper.updateById(role);
        // 删除角色与部门关联
        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().eq(SysRoleDept::getRoleId, role.getRoleId()));
        // 新增角色和部门信息（数据权限）
        return insertRoleDept(bo);
    }

    /**
     * 新增角色菜单信息
     *
     * @param role 角色对象
     */
    private int insertRoleMenu(SysRoleBo role) {
        int rows = 1;
        // 新增用户与角色管理
        List<SysRoleMenu> list = new ArrayList<>();
        for (Long menuId : role.getMenuIds()) {
            SysRoleMenu rm = new SysRoleMenu();
            rm.setRoleId(role.getRoleId());
            rm.setMenuId(menuId);
            list.add(rm);
        }
        if (list.size() > 0) {
            rows = roleMenuMapper.insertBatch(list) ? list.size() : 0;
        }
        return rows;
    }

    /**
     * 新增角色部门信息(数据权限)
     *
     * @param role 角色对象
     */
    private int insertRoleDept(SysRoleBo role) {
        int rows = 1;
        // 新增角色与部门（数据权限）管理
        List<SysRoleDept> list = new ArrayList<>();
        for (Long deptId : role.getDeptIds()) {
            SysRoleDept rd = new SysRoleDept();
            rd.setRoleId(role.getRoleId());
            rd.setDeptId(deptId);
            list.add(rd);
        }
        if (list.size() > 0) {
            rows = roleDeptMapper.insertBatch(list) ? list.size() : 0;
        }
        return rows;
    }

    /**
     * 通过角色ID删除角色
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteRoleById(Long roleId) {
        // 删除角色与菜单关联
        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        // 删除角色与部门关联
        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().eq(SysRoleDept::getRoleId, roleId));
        return baseMapper.deleteById(roleId);
    }

    /**
     * 批量删除角色信息
     *
     * @param roleIds 需要删除的角色ID
     * @return 结果
     */
    @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, allEntries = true)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteRoleByIds(Long[] roleIds) {
        for (Long roleId : roleIds) {
            SysRole role = baseMapper.selectById(roleId);
            checkRoleAllowed(BeanUtil.toBean(role, SysRoleBo.class));
            checkRoleDataScope(roleId);
            if (countUserRoleByRoleId(roleId) > 0) {
                throw new ServiceException(String.format("%1$s已分配，不能删除!", role.getRoleName()));
            }
        }
        List<Long> ids = Arrays.asList(roleIds);
        // 删除角色与菜单关联
        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, ids));
        // 删除角色与部门关联
        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().in(SysRoleDept::getRoleId, ids));
        return baseMapper.deleteByIds(ids);
    }

    /**
     * 取消授权用户角色
     *
     * @param userRole 用户和角色关联信息
     * @return 结果
     */
    @Override
    public int deleteAuthUser(SysUserRole userRole) {
        int rows = userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
            .eq(SysUserRole::getRoleId, userRole.getRoleId())
            .eq(SysUserRole::getUserId, userRole.getUserId()));
        if (rows > 0) {
            cleanOnlineUser(List.of(userRole.getUserId()));
        }
        return rows;
    }

    /**
     * 批量取消授权用户角色
     *
     * @param roleId  角色ID
     * @param userIds 需要取消授权的用户数据ID
     * @return 结果
     */
    @Override
    public int deleteAuthUsers(Long roleId, Long[] userIds) {
        List<Long> ids = List.of(userIds);
        int rows = userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
            .eq(SysUserRole::getRoleId, roleId)
            .in(SysUserRole::getUserId, ids));
        if (rows > 0) {
            cleanOnlineUser(ids);
        }
        return rows;
    }

    /**
     * 批量选择授权用户角色
     *
     * @param roleId  角色ID
     * @param userIds 需要授权的用户数据ID
     * @return 结果
     */
    @Override
    public int insertAuthUsers(Long roleId, Long[] userIds) {
        // 新增用户与角色管理
        int rows = 1;
        List<Long> ids = List.of(userIds);
        List<SysUserRole> list = StreamUtils.toList(ids, userId -> {
            SysUserRole ur = new SysUserRole();
            ur.setUserId(userId);
            ur.setRoleId(roleId);
            return ur;
        });
        if (CollUtil.isNotEmpty(list)) {
            rows = userRoleMapper.insertBatch(list) ? list.size() : 0;
        }
        if (rows > 0) {
            cleanOnlineUser(ids);
        }
        return rows;
    }

    @Override
    public void cleanOnlineUserByRole(Long roleId) {
        // 如果角色未绑定用户 直接返回
        Long num = userRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
        if (num == 0) {
            return;
        }
        List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
        if (CollUtil.isEmpty(keys)) {
            return;
        }
        // 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作
        keys.parallelStream().forEach(key -> {
            String token = StringUtils.substringAfterLast(key, ":");
            // 如果已经过期则跳过
            if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) {
                return;
            }
            LoginUser loginUser = LoginHelper.getLoginUser(token);
            if (ObjectUtil.isNull(loginUser) || CollUtil.isEmpty(loginUser.getRoles())) {
                return;
            }
            if (loginUser.getRoles().stream().anyMatch(r -> r.getRoleId().equals(roleId))) {
                try {
                    StpUtil.logoutByTokenValue(token);
                } catch (NotLoginException ignored) {
                }
            }
        });
    }

    @Override
    public void cleanOnlineUser(List<Long> userIds) {
        List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
        if (CollUtil.isEmpty(keys)) {
            return;
        }
        // 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作
        keys.parallelStream().forEach(key -> {
            String token = StringUtils.substringAfterLast(key, ":");
            // 如果已经过期则跳过
            if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) {
                return;
            }
            LoginUser loginUser = LoginHelper.getLoginUser(token);
            if (ObjectUtil.isNull(loginUser)) {
                return;
            }
            if (userIds.contains(loginUser.getUserId())) {
                try {
                    StpUtil.logoutByTokenValue(token);
                } catch (NotLoginException ignored) {
                }
            }
        });
    }

    /**
     * 查询角色数据权限配置列表
     *
     * @param roleId 角色ID
     * @return 数据权限配置列表
     */
    @Override
    public List<SysRoleDataScopeConfigVo> selectRoleDataScopeConfig(Long roleId) {
        List<SysRoleDataScopeConfig> configs = roleDataScopeConfigMapper.selectList(
            new LambdaQueryWrapper<SysRoleDataScopeConfig>()
                .eq(SysRoleDataScopeConfig::getRoleId, roleId)
                .orderByAsc(SysRoleDataScopeConfig::getMenuId, SysRoleDataScopeConfig::getPermission)
        );
        
        List<SysRoleDataScopeConfigVo> result = MapstructUtils.convert(configs, SysRoleDataScopeConfigVo.class);
        
        // 填充菜单名称
        if (CollUtil.isNotEmpty(result)) {
            Set<Long> menuIds = StreamUtils.toSet(result, SysRoleDataScopeConfigVo::getMenuId);
            List<SysMenu> menuList = menuMapper.selectList(
                new LambdaQueryWrapper<SysMenu>()
                    .select(SysMenu::getMenuId, SysMenu::getMenuName)
                    .in(SysMenu::getMenuId, menuIds)
            );
            Map<Long, String> menuNameMap = StreamUtils.toMap(menuList, SysMenu::getMenuId, SysMenu::getMenuName);
            
            result.forEach(vo -> vo.setMenuName(menuNameMap.get(vo.getMenuId())));
        }
        
        return result;
    }

    /**
     * 更新角色数据权限配置
     *
     * @param configs 数据权限配置列表
     * @return 更新结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateRoleDataScopeConfig(List<SysRoleDataScopeConfigBo> configs) {
        log.info("==== 开始更新角色数据权限配置 ====");
        log.info("接收到的配置数据数量: {}", configs != null ? configs.size() : 0);
        
        if (CollUtil.isNotEmpty(configs)) {
            log.info("配置详情:");
            for (int i = 0; i < configs.size(); i++) {
                SysRoleDataScopeConfigBo config = configs.get(i);
                log.info("配置[{}]: roleId={}, menuId={}, permission={}, filterField={}, filterValues={}", 
                    i, config.getRoleId(), config.getMenuId(), config.getPermission(), 
                    config.getFilterField(), config.getFilterValues());
            }
        }
        
        Long roleId = null;
        
        // 获取角色ID
        if (CollUtil.isNotEmpty(configs)) {
            roleId = configs.get(0).getRoleId();
        }
        
        if (ObjectUtil.isNull(roleId)) {
            log.error("角色ID不能为空");
            throw new ServiceException("角色ID不能为空");
        }
        
        log.info("开始为角色[{}]更新数据权限配置", roleId);
        
        // 先删除该角色的所有数据权限配置
        int deleteCount = roleDataScopeConfigMapper.delete(
            new LambdaQueryWrapper<SysRoleDataScopeConfig>()
                .eq(SysRoleDataScopeConfig::getRoleId, roleId)
        );
        log.info("删除角色[{}]的数据权限配置[{}]条", roleId, deleteCount);
        
        // 如果配置列表为空，则只删除不插入（用于清空配置的场景）
        if (CollUtil.isEmpty(configs)) {
            log.info("配置列表为空，只删除不插入");
            return deleteCount;
        }
        
        // 转换为实体对象并插入新的配置
        List<SysRoleDataScopeConfig> entities = MapstructUtils.convert(configs, SysRoleDataScopeConfig.class);
        log.info("转换后的实体数量: {}", entities != null ? entities.size() : 0);
        
        int insertCount = 0;
        
        for (int i = 0; i < entities.size(); i++) {
            SysRoleDataScopeConfig entity = entities.get(i);
            log.info("准备插入配置[{}]: roleId={}, menuId={}, permission={}, filterField={}, filterValues={}", 
                i, entity.getRoleId(), entity.getMenuId(), entity.getPermission(), 
                entity.getFilterField(), entity.getFilterValues());
            
            // 设置默认值
            if (StringUtils.isBlank(entity.getFilterType())) {
                entity.setFilterType("IN");
                log.info("设置默认过滤类型: IN");
            }
            if (StringUtils.isBlank(entity.getEnableStatus())) {
                entity.setEnableStatus("0"); // 默认启用
                log.info("设置默认启用状态: 0");
            }
            
            // 根据权限标识推断并设置表名
            if (StringUtils.isNotBlank(entity.getPermission()) && StringUtils.isBlank(entity.getTableName())) {
                String tableName = getTableNameByPermission(entity.getPermission());
                entity.setTableName(tableName);
                log.info("推断表名: {} -> {}", entity.getPermission(), tableName);
            }
            
            try {
                int result = roleDataScopeConfigMapper.insert(entity);
                insertCount += result;
                log.info("插入配置[{}]成功，影响行数: {}", i, result);
            } catch (Exception e) {
                log.error("插入配置[{}]失败: {}", i, e.getMessage(), e);
                throw e;
            }
        }
        
        log.info("为角色[{}]插入数据权限配置完成，总共插入[{}]条", roleId, insertCount);
        log.info("==== 角色数据权限配置更新完成 ====");
        return insertCount;
    }

    /**
     * 删除角色的所有数据权限配置
     *
     * @param roleId 角色ID
     * @return 删除结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteRoleDataScopeConfig(Long roleId) {
        if (ObjectUtil.isNull(roleId)) {
            throw new ServiceException("角色ID不能为空");
        }
        
        int deleteCount = roleDataScopeConfigMapper.delete(
            new LambdaQueryWrapper<SysRoleDataScopeConfig>()
                .eq(SysRoleDataScopeConfig::getRoleId, roleId)
        );
        log.info("删除角色[{}]的所有数据权限配置[{}]条", roleId, deleteCount);
        return deleteCount;
    }

    /**
     * 获取可用菜单权限列表
     * 用于数据权限配置时选择菜单和接口
     *
     * @return 菜单权限列表
     */
    @Override
    public List<MenuPermissionVo> getAvailableMenuPermissions() {
        // 查询所有启用的菜单
        List<SysMenu> menus = menuMapper.selectList(
            new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getStatus, "0") // 启用状态
                .eq(SysMenu::getMenuType, "C") // 菜单类型：C=菜单
                .isNotNull(SysMenu::getComponent) // 有组件路径
                .orderByAsc(SysMenu::getOrderNum)
        );
        
        List<MenuPermissionVo> result = new ArrayList<>();
        
        for (SysMenu menu : menus) {
            MenuPermissionVo vo = new MenuPermissionVo();
            vo.setMenuId(menu.getMenuId());
            vo.setMenuName(menu.getMenuName());
            vo.setPath(menu.getPath());
            vo.setComponent(menu.getComponent());
            
            // 查询该菜单下的权限按钮
            List<SysMenu> permissions = menuMapper.selectList(
                new LambdaQueryWrapper<SysMenu>()
                    .eq(SysMenu::getParentId, menu.getMenuId())
                    .eq(SysMenu::getMenuType, "F") // 按钮类型：F=按钮
                    .eq(SysMenu::getStatus, "0") // 启用状态
                    .isNotNull(SysMenu::getPerms) // 有权限标识
                    .orderByAsc(SysMenu::getOrderNum)
            );
            
            List<MenuPermissionVo.PermissionInfo> permissionList = new ArrayList<>();
            for (SysMenu permission : permissions) {
                MenuPermissionVo.PermissionInfo permissionInfo = new MenuPermissionVo.PermissionInfo();
                permissionInfo.setPermission(permission.getPerms());
                permissionInfo.setPermissionName(permission.getMenuName());
                
                // 从权限标识中提取权限类型（最后一部分）
                String[] parts = permission.getPerms().split(":");
                if (parts.length > 0) {
                    permissionInfo.setPermissionType(parts[parts.length - 1]);
                }
                
                permissionList.add(permissionInfo);
            }
            
            vo.setPermissions(permissionList);
            result.add(vo);
        }
        
        return result;
    }

    /**
     * 获取菜单列表权限
     * 仅返回列表查询类型的权限，用于数据权限配置
     *
     * @return 菜单列表权限
     */
    @Override
    public List<MenuPermissionVo> getMenuListPermissions() {
        // 查询所有启用的菜单，这些菜单本身就代表列表页面
        List<SysMenu> menus = menuMapper.selectList(
            new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getStatus, "0") // 启用状态
                .eq(SysMenu::getMenuType, "C") // 菜单类型：C=菜单
                .isNotNull(SysMenu::getComponent) // 有组件路径
                .isNotNull(SysMenu::getPerms) // 有权限标识
                .like(SysMenu::getPerms, ":list") // 权限标识包含list
                .orderByAsc(SysMenu::getOrderNum)
        );
        
        List<MenuPermissionVo> result = new ArrayList<>();
        
        for (SysMenu menu : menus) {
            MenuPermissionVo vo = new MenuPermissionVo();
            vo.setMenuId(menu.getMenuId());
            vo.setMenuName(menu.getMenuName());
            vo.setPath(menu.getPath());
            vo.setComponent(menu.getComponent());
            
            // 菜单本身就是列表权限
            List<MenuPermissionVo.PermissionInfo> permissionList = new ArrayList<>();
            MenuPermissionVo.PermissionInfo permissionInfo = new MenuPermissionVo.PermissionInfo();
            permissionInfo.setPermission(menu.getPerms());
            permissionInfo.setPermissionName(menu.getMenuName());
            permissionInfo.setPermissionType("list");
            
            permissionList.add(permissionInfo);
            vo.setPermissions(permissionList);
            result.add(vo);
        }
        
        return result;
    }

    /**
     * 根据权限标识获取对应表的字段列表
     * 支持多数据源环境，动态从所有数据源中查询表结构
     *
     * @param permission 权限标识（如：system:user:list）
     * @return 表字段列表
     */
    @Override
    public List<String> getTableFieldsByPermission(String permission) {
        List<String> fields = new ArrayList<>();
        
        if (StringUtils.isBlank(permission)) {
            log.warn("权限标识为空");
            return fields;
        }
        
        // 根据权限标识推断表名
        String tableName = getTableNameByPermission(permission);
        if (StringUtils.isBlank(tableName)) {
            log.warn("无法根据权限标识 {} 推断出表名", permission);
            return fields;
        }
        
        log.info("开始获取表字段: permission={}, tableName={}", permission, tableName);
        
        try {
            // 动态查询表结构（支持多数据源）
            fields = getTableColumns(tableName);
            
            if (fields.isEmpty()) {
                log.warn("表 {} 不存在或无字段，使用通用字段", tableName);
                // 如果动态查询失败，返回通用字段
                fields = Arrays.asList(
                    "id", "name", "status", "create_by", "create_time", 
                    "update_by", "update_time", "remark"
                );
            } else {
                log.info("成功获取表 {} 的字段列表: {} 个字段", tableName, fields.size());
            }
            
        } catch (Exception e) {
            log.error("获取表字段失败: permission={}, tableName={}, error={}", permission, tableName, e.getMessage());
            // 如果动态查询失败，返回通用字段
            fields = Arrays.asList(
                "id", "name", "status", "create_by", "create_time", 
                "update_by", "update_time", "remark"
            );
        }
        
        return fields;
    }
    
    /**
     * 根据权限标识动态推断表名
     * 完全基于命名约定和数据库查询，无硬编码映射
     * 
     * @param permission 权限标识
     * @return 表名
     */
    private String getTableNameByPermission(String permission) {
        if (StringUtils.isBlank(permission)) {
            return null;
        }
        
        String[] parts = permission.split(":");
        if (parts.length < 2) {
            return null;
        }
        
        String namespace = parts[0]; // 命名空间（如：system, workflow）
        String module = parts[1];    // 模块名（如：user, role）
        
        log.debug("开始动态推断表名: namespace={}, module={}", namespace, module);
        
        // 1. 基于命名约定的智能推断
        String inferredTableName = inferTableNameByConvention(namespace, module);
        if (StringUtils.isNotBlank(inferredTableName)) {
            log.info("成功推断表名: {} -> {} (基于命名约定)", permission, inferredTableName);
            return inferredTableName;
        }
        
        // 2. 基于模糊匹配的智能查找
        String matchedTableName = findTableByFuzzyMatch(module);
        if (StringUtils.isNotBlank(matchedTableName)) {
            log.info("成功推断表名: {} -> {} (基于模糊匹配)", permission, matchedTableName);
            return matchedTableName;
        }
        
        log.warn("无法推断权限 {} 对应的表名", permission);
        return null;
    }
    
    /**
     * 基于命名约定动态推断表名
     * 根据常见的数据库表命名规则进行智能推断
     * 
     * @param namespace 命名空间（如：system, workflow等）
     * @param module 模块名（如：user, role等）
     * @return 推断的表名
     */
    private String inferTableNameByConvention(String namespace, String module) {
        if (StringUtils.isBlank(module)) {
            return null;
        }
        
        // 先转换模块名格式（驼峰转下划线）
        String underscoreModule = camelToUnderscore(module);
        
        // 尝试多种命名规则推断表名（按优先级排序）
        List<String> candidateTableNames = new ArrayList<>();
        
        // 规则1: 根据命名空间添加前缀
        switch (namespace.toLowerCase()) {
            case "system":
                candidateTableNames.add("sys_" + underscoreModule);
                break;
            case "workflow":
                candidateTableNames.add("wf_" + underscoreModule);
                break;
            case "test":
                candidateTableNames.add("test_" + underscoreModule);
                break;
            default:
                // 自定义命名空间：namespace_module
                candidateTableNames.add(namespace.toLowerCase() + "_" + underscoreModule);
                break;
        }
        
        // 规则2: 直接使用转换后的模块名
        candidateTableNames.add(underscoreModule);
        
        // 规则3: 原始模块名（兼容非下划线格式）
        if (!underscoreModule.equals(module)) {
            candidateTableNames.add(module.toLowerCase());
        }
        
        // 规则4: 常见前缀尝试
        candidateTableNames.add("t_" + underscoreModule);      // t_前缀
        candidateTableNames.add("tb_" + underscoreModule);     // tb_前缀
        candidateTableNames.add("tbl_" + underscoreModule);    // tbl_前缀
        
        // 验证表是否存在
        for (String tableName : candidateTableNames) {
            if (tableExists(tableName)) {
                log.debug("命名约定推断成功: {}:{} -> {}", namespace, module, tableName);
                return tableName;
            }
        }
        
        return null;
    }
    
    /**
     * 通过模糊匹配查找表名
     * 当命名约定推断失败时，通过查询数据库中的所有表进行模糊匹配
     * 
     * @param module 模块名
     * @return 匹配的表名
     */
    private String findTableByFuzzyMatch(String module) {
        if (StringUtils.isBlank(module)) {
            return null;
        }
        
        try {
            List<String> allTables = getAllTableNames();
            String modulePattern = camelToUnderscore(module).toLowerCase();
            
            // 匹配策略（按优先级排序）
            List<String> matchResults = new ArrayList<>();
            
            for (String tableName : allTables) {
                String lowerTableName = tableName.toLowerCase();
                
                // 策略1: 精确匹配（去掉前缀后完全匹配）
                if (lowerTableName.endsWith("_" + modulePattern) || 
                    lowerTableName.equals(modulePattern)) {
                    matchResults.add(0, tableName); // 添加到列表开头（最高优先级）
                    continue;
                }
                
                // 策略2: 包含匹配
                if (lowerTableName.contains(modulePattern)) {
                    matchResults.add(tableName);
                    continue;
                }
                
                // 策略3: 模糊匹配（处理单复数、简写等情况）
                if (isFuzzyMatch(lowerTableName, modulePattern)) {
                    matchResults.add(tableName);
                }
            }
            
            if (!matchResults.isEmpty()) {
                String bestMatch = matchResults.get(0);
                log.debug("模糊匹配成功: {} -> {} (从{}个候选中选择)", module, bestMatch, matchResults.size());
                return bestMatch;
            }
            
        } catch (Exception e) {
            log.warn("模糊匹配查找表名失败: module={}, error={}", module, e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 获取所有数据源中的表名
     * 支持多数据源环境，自动搜索所有配置的数据源
     */
    private List<String> getAllTableNames() {
        Set<String> allTableNames = new HashSet<>();
        
        // 获取所有配置的数据源
        Map<String, DataSource> allDataSources = getAllDataSources();
        
        for (Map.Entry<String, DataSource> entry : allDataSources.entrySet()) {
            String dataSourceName = entry.getKey();
            DataSource ds = entry.getValue();
            
            try {
                List<String> tableNames = getTableNamesFromDataSource(ds, dataSourceName);
                allTableNames.addAll(tableNames);
                log.debug("从数据源 {} 获取到 {} 个表", dataSourceName, tableNames.size());
            } catch (Exception e) {
                log.warn("从数据源 {} 获取表名失败: {}", dataSourceName, e.getMessage());
            }
        }
        
        log.info("总共从 {} 个数据源获取到 {} 个表", allDataSources.size(), allTableNames.size());
        return new ArrayList<>(allTableNames);
    }
    
    /**
     * 获取所有配置的数据源
     */
    private Map<String, DataSource> getAllDataSources() {
        Map<String, DataSource> dataSources = new LinkedHashMap<>();
        
        try {
            // 获取动态数据源
            DynamicRoutingDataSource dynamicDS = SpringUtils.getBean(DynamicRoutingDataSource.class);
            Map<String, DataSource> allDataSources = dynamicDS.getDataSources();
            
            // 添加所有配置的数据源
            dataSources.putAll(allDataSources);
            
            // 确保包含当前数据源
            if (!dataSources.containsKey("current")) {
                dataSources.put("current", dataSource);
            }
            
            log.debug("发现数据源: {}", dataSources.keySet());
            
        } catch (Exception e) {
            log.warn("获取动态数据源失败，使用默认数据源: {}", e.getMessage());
            // 回退到默认数据源
            dataSources.put("default", dataSource);
        }
        
        return dataSources;
    }
    
    /**
     * 从指定数据源获取表名列表
     */
    private List<String> getTableNamesFromDataSource(DataSource ds, String dataSourceName) {
        List<String> tableNames = new ArrayList<>();
        
        try (Connection connection = ds.getConnection()) {
            String sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES " +
                        "WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE'";
            
            try (PreparedStatement stmt = connection.prepareStatement(sql);
                 ResultSet rs = stmt.executeQuery()) {
                
                while (rs.next()) {
                    String tableName = rs.getString("TABLE_NAME");
                    if (StringUtils.isNotBlank(tableName)) {
                        tableNames.add(tableName);
                    }
                }
            }
        } catch (SQLException e) {
            log.warn("从数据源 {} 获取表名失败: {}", dataSourceName, e.getMessage());
        }
        
        return tableNames;
    }
    
    /**
     * 判断是否为模糊匹配
     * 处理单复数、简写、常见变形等情况
     */
    private boolean isFuzzyMatch(String tableName, String modulePattern) {
        // 移除常见前缀进行比较
        String cleanTableName = tableName;
        String[] prefixes = {"sys_", "wf_", "test_", "t_", "tb_", "tbl_"};
        for (String prefix : prefixes) {
            if (cleanTableName.startsWith(prefix)) {
                cleanTableName = cleanTableName.substring(prefix.length());
                break;
            }
        }
        
        // 策略1: 单复数匹配
        if (cleanTableName.equals(modulePattern + "s") || 
            cleanTableName.equals(modulePattern + "es") ||
            (modulePattern.endsWith("s") && cleanTableName.equals(modulePattern.substring(0, modulePattern.length() - 1)))) {
            return true;
        }
        
        // 策略2: 常见简写匹配
        Map<String, String> abbreviations = new HashMap<>();
        abbreviations.put("config", "cfg");
        abbreviations.put("configuration", "config");
        abbreviations.put("information", "info");
        abbreviations.put("management", "mgmt");
        abbreviations.put("administration", "admin");
        
        for (Map.Entry<String, String> entry : abbreviations.entrySet()) {
            if ((modulePattern.equals(entry.getKey()) && cleanTableName.contains(entry.getValue())) ||
                (modulePattern.equals(entry.getValue()) && cleanTableName.contains(entry.getKey()))) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 驼峰命名转下划线
     */
    private String camelToUnderscore(String camelCase) {
        return camelCase.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
    }
    
    /**
     * 检查表是否存在于任意数据源中
     * 支持多数据源环境，会在所有数据源中查找指定表
     */
    private boolean tableExists(String tableName) {
        Map<String, DataSource> allDataSources = getAllDataSources();
        
        for (Map.Entry<String, DataSource> entry : allDataSources.entrySet()) {
            String dataSourceName = entry.getKey();
            DataSource ds = entry.getValue();
            
            if (tableExistsInDataSource(tableName, ds, dataSourceName)) {
                log.debug("表 {} 存在于数据源 {}", tableName, dataSourceName);
                return true;
            }
        }
        
        log.debug("表 {} 在所有数据源中都不存在", tableName);
        return false;
    }
    
    /**
     * 检查表是否存在于指定数据源
     */
    private boolean tableExistsInDataSource(String tableName, DataSource ds, String dataSourceName) {
        try (Connection connection = ds.getConnection()) {
            String sql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES " +
                        "WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?";
            
            try (PreparedStatement stmt = connection.prepareStatement(sql)) {
                stmt.setString(1, tableName);
                try (ResultSet rs = stmt.executeQuery()) {
                    if (rs.next()) {
                        return rs.getInt(1) > 0;
                    }
                }
            }
        } catch (SQLException e) {
            log.warn("在数据源 {} 中检查表 {} 是否存在失败: {}", dataSourceName, tableName, e.getMessage());
        }
        return false;
    }
    
    /**
     * 动态查询表的字段列表
     * 支持多数据源环境，自动在所有数据源中查找表并获取字段
     * 
     * @param tableName 表名
     * @return 字段列表
     */
    private List<String> getTableColumns(String tableName) {
        Map<String, DataSource> allDataSources = getAllDataSources();
        
        // 优先在主数据源中查找
        if (allDataSources.containsKey("master")) {
            List<String> columns = getTableColumnsFromDataSource(tableName, allDataSources.get("master"), "master");
            if (!columns.isEmpty()) {
                log.debug("在主数据源中找到表 {} 的字段列表", tableName);
                return columns;
            }
        }
        
        // 在所有数据源中查找表
        for (Map.Entry<String, DataSource> entry : allDataSources.entrySet()) {
            String dataSourceName = entry.getKey();
            DataSource ds = entry.getValue();
            
            // 跳过已经检查过的主数据源
            if ("master".equals(dataSourceName)) {
                continue;
            }
            
            List<String> columns = getTableColumnsFromDataSource(tableName, ds, dataSourceName);
            if (!columns.isEmpty()) {
                log.info("在数据源 {} 中找到表 {} 的字段列表: {}", dataSourceName, tableName, columns.size());
                return columns;
            }
        }
        
        log.warn("在所有数据源中都未找到表 {} 的字段信息", tableName);
        return new ArrayList<>();
    }
    
    /**
     * 从指定数据源查询表的字段列表
     */
    private List<String> getTableColumnsFromDataSource(String tableName, DataSource ds, String dataSourceName) {
        List<String> columns = new ArrayList<>();
        
        try (Connection connection = ds.getConnection()) {
            // 使用INFORMATION_SCHEMA查询表结构
            String sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS " +
                        "WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? " +
                        "ORDER BY ORDINAL_POSITION";
            
            try (PreparedStatement stmt = connection.prepareStatement(sql)) {
                stmt.setString(1, tableName);
                
                try (ResultSet rs = stmt.executeQuery()) {
                    while (rs.next()) {
                        String columnName = rs.getString("COLUMN_NAME");
                        if (StringUtils.isNotBlank(columnName)) {
                            columns.add(columnName);
                        }
                    }
                }
            }
        } catch (SQLException e) {
            log.debug("在数据源 {} 中查询表 {} 结构失败: {}", dataSourceName, tableName, e.getMessage());
        }
        
        return columns;
    }

}
